# ============================================================================ #
# Copyright (c) 2022 - 2025 NVIDIA Corporation & Affiliates.                   #
# All rights reserved.                                                         #
#                                                                              #
# This source code and the accompanying materials are made available under     #
# the terms of the Apache License 2.0 which accompanies this distribution.     #
# ============================================================================ #

# RUN: PYTHONPATH=../../ pytest -rP  %s | FileCheck %s

import cudaq


def test_openqasm2_synth():

    @cudaq.kernel
    def ghz(numQubits: int):
        qubits = cudaq.qvector(numQubits)
        h(qubits.front())
        for i in range(numQubits - 1):
            x.ctrl(qubits[i], qubits[i + 1])

    synth = cudaq.synthesize(ghz, 5)
    print(cudaq.translate(synth, format='openqasm2'))


# CHECK: // Code generated by NVIDIA's nvq++ compiler
# CHECK: OPENQASM 2.0;

# CHECK: include "qelib1.inc";

# CHECK: qreg var0[5];
# CHECK: h var0[0];
# CHECK: cx var0[0], var0[1];
# CHECK: cx var0[1], var0[2];
# CHECK: cx var0[2], var0[3];
# CHECK: cx var0[3], var0[4];


def test_openqasm2_gates():

    @cudaq.kernel
    def gates():
        q = cudaq.qubit()
        ctrl0 = cudaq.qubit()
        ctrl1 = cudaq.qubit()
        h(q)
        x(q)
        y(q)
        z(q)
        s(q)
        t(q)
        h.ctrl(ctrl0, q)
        z.ctrl(ctrl0, ctrl1, q)
        rx.ctrl(np.pi, ctrl0, q)
        ry.ctrl(np.pi, ctrl0, q)
        rz.ctrl(np.pi, ctrl0, q)
        r1.ctrl(np.pi, ctrl0, q)
        r1(np.pi, q)
        rx(np.pi, q)
        rx.adj(np.pi, q)
        ry(np.pi, q)
        ry.adj(np.pi, q)
        rz(np.pi, q)
        rz.adj(np.pi, q)
        mx(q)
        my(q)
        mz(q)

    print(cudaq.translate(gates, format="openqasm2"))


# CHECK: // Code generated by NVIDIA's nvq++ compiler
# CHECK: OPENQASM 2.0;

# CHECK: include "qelib1.inc";

# CHECK: qreg var0[3];
# CHECK: h var0[0];
# CHECK: x var0[0];
# CHECK: y var0[0];
# CHECK: z var0[0];
# CHECK: rz(1.570796e+00) var0[0];
# CHECK: rx(1.570796e+00) var0[0];
# CHECK: rz(0.000000e+00) var0[0];
# CHECK: rx(-1.570796e+00) var0[0];
# CHECK: rz(0.000000e+00) var0[0];
# CHECK: rz(7.853982e-01) var0[0];
# CHECK: rx(1.570796e+00) var0[0];
# CHECK: rz(0.000000e+00) var0[0];
# CHECK: rx(-1.570796e+00) var0[0];
# CHECK: rz(0.000000e+00) var0[0];
# CHECK: rz(1.570796e+00) var0[0];
# CHECK: rx(1.570796e+00) var0[0];
# CHECK: rz(0.000000e+00) var0[0];
# CHECK: rx(-1.570796e+00) var0[0];
# CHECK: rz(0.000000e+00) var0[0];
# CHECK: h var0[0];
# CHECK: rz(7.853982e-01) var0[0];
# CHECK: rx(1.570796e+00) var0[0];
# CHECK: rz(0.000000e+00) var0[0];
# CHECK: rx(-1.570796e+00) var0[0];
# CHECK: rz(0.000000e+00) var0[0];
# CHECK: cx var0[1], var0[0];
# CHECK: rz(-7.853982e-01) var0[0];
# CHECK: rx(1.570796e+00) var0[0];
# CHECK: rz(0.000000e+00) var0[0];
# CHECK: rx(-1.570796e+00) var0[0];
# CHECK: rz(0.000000e+00) var0[0];
# CHECK: h var0[0];
# CHECK: rz(-1.570796e+00) var0[0];
# CHECK: rx(1.570796e+00) var0[0];
# CHECK: rz(0.000000e+00) var0[0];
# CHECK: rx(-1.570796e+00) var0[0];
# CHECK: rz(0.000000e+00) var0[0];
# CHECK: cx var0[2], var0[0];
# CHECK: rz(-7.853982e-01) var0[0];
# CHECK: rx(1.570796e+00) var0[0];
# CHECK: rz(0.000000e+00) var0[0];
# CHECK: rx(-1.570796e+00) var0[0];
# CHECK: rz(0.000000e+00) var0[0];
# CHECK: cx var0[1], var0[0];
# CHECK: rz(7.853982e-01) var0[0];
# CHECK: rx(1.570796e+00) var0[0];
# CHECK: rz(0.000000e+00) var0[0];
# CHECK: rx(-1.570796e+00) var0[0];
# CHECK: rz(0.000000e+00) var0[0];
# CHECK: cx var0[2], var0[0];
# CHECK: rz(-7.853982e-01) var0[0];
# CHECK: rx(1.570796e+00) var0[0];
# CHECK: rz(0.000000e+00) var0[0];
# CHECK: rx(-1.570796e+00) var0[0];
# CHECK: rz(0.000000e+00) var0[0];
# CHECK: cx var0[1], var0[0];
# CHECK: rz(7.853982e-01) var0[0];
# CHECK: rx(1.570796e+00) var0[0];
# CHECK: rz(0.000000e+00) var0[0];
# CHECK: rx(-1.570796e+00) var0[0];
# CHECK: rz(0.000000e+00) var0[0];
# CHECK: cx var0[1], var0[2];
# CHECK: rz(-7.853982e-01) var0[2];
# CHECK: rx(1.570796e+00) var0[2];
# CHECK: rz(0.000000e+00) var0[2];
# CHECK: rx(-1.570796e+00) var0[2];
# CHECK: rz(0.000000e+00) var0[2];
# CHECK: cx var0[1], var0[2];
# CHECK: rz(7.853982e-01) var0[2];
# CHECK: rx(1.570796e+00) var0[2];
# CHECK: rz(0.000000e+00) var0[2];
# CHECK: rx(-1.570796e+00) var0[2];
# CHECK: rz(0.000000e+00) var0[2];
# CHECK: rz(7.853982e-01) var0[1];
# CHECK: rx(1.570796e+00) var0[1];
# CHECK: rz(0.000000e+00) var0[1];
# CHECK: rx(-1.570796e+00) var0[1];
# CHECK: rz(0.000000e+00) var0[1];
# CHECK: rz(1.570796e+00) var0[0];
# CHECK: rx(1.570796e+00) var0[0];
# CHECK: rz(0.000000e+00) var0[0];
# CHECK: rx(-1.570796e+00) var0[0];
# CHECK: rz(0.000000e+00) var0[0];
# CHECK: cx var0[1], var0[0];
# CHECK: ry(-1.570796e+00) var0[0];
# CHECK: cx var0[1], var0[0];
# CHECK: ry(1.570796e+00) var0[0];
# CHECK: rz(-1.570796e+00) var0[0];
# CHECK: ry(1.570796e+00) var0[0];
# CHECK: cx var0[1], var0[0];
# CHECK: ry(-1.570796e+00) var0[0];
# CHECK: cx var0[1], var0[0];
# CHECK: rz(1.570796e+00) var0[0];
# CHECK: cx var0[1], var0[0];
# CHECK: rz(-1.570796e+00) var0[0];
# CHECK: cx var0[1], var0[0];
# CHECK: rz(1.570796e+00) var0[1];
# CHECK: rx(1.570796e+00) var0[1];
# CHECK: rz(0.000000e+00) var0[1];
# CHECK: rx(-1.570796e+00) var0[1];
# CHECK: rz(0.000000e+00) var0[1];
# CHECK: cx var0[1], var0[0];
# CHECK: rz(-1.570796e+00) var0[0];
# CHECK: rx(1.570796e+00) var0[0];
# CHECK: rz(0.000000e+00) var0[0];
# CHECK: rx(-1.570796e+00) var0[0];
# CHECK: rz(0.000000e+00) var0[0];
# CHECK: cx var0[1], var0[0];
# CHECK: rz(1.570796e+00) var0[0];
# CHECK: rx(1.570796e+00) var0[0];
# CHECK: rz(0.000000e+00) var0[0];
# CHECK: rx(-1.570796e+00) var0[0];
# CHECK: rz(0.000000e+00) var0[0];
# CHECK: rz(3.141593e+00) var0[0];
# CHECK: rx(1.570796e+00) var0[0];
# CHECK: rz(0.000000e+00) var0[0];
# CHECK: rx(-1.570796e+00) var0[0];
# CHECK: rz(0.000000e+00) var0[0];
# CHECK: rx(3.141593e+00) var0[0];
# CHECK: rx(-3.141593e+00) var0[0];
# CHECK: ry(3.141593e+00) var0[0];
# CHECK: ry(-3.141593e+00) var0[0];
# CHECK: rz(3.141593e+00) var0[0];
# CHECK: rz(-3.141593e+00) var0[0];
# CHECK: h var0[0];
# CHECK: creg var4[1];
# CHECK: measure var0[0] -> var4[0];
# CHECK: sdg var0[0];
# CHECK: h var0[0];
# CHECK: creg var5[1];
# CHECK: measure var0[0] -> var5[0];
# CHECK: creg var6[1];
# CHECK: measure var0[0] -> var6[0];
